#pragma once

#include <string>
#include <memory>
#include <cstdint>
#include <initializer_list>
#include <list>
#include <functional>
#include "component.hh"
#include "../corelib/object_pool.hpp"
#include "../corelib/singleton.hpp"
#include "../corelib/util/allocator.hh"

namespace kratos { namespace engine {

// Implementation for ComponentManager
class ComponentManagerImpl : public ComponentManager {
    using ComponentMap = std::unordered_map<std::string, std::shared_ptr<Component>>;
    ComponentMap componentMap_; // { component name, std::shared_ptr<Component>}

public:
    // ctor
    ComponentManagerImpl();
    // dtor
    virtual ~ComponentManagerImpl();
    // main cycle
    void update();
    virtual bool registerComponent(Component* ptr) override;
    virtual bool unregisterComponent(const std::string& name) override;
    virtual std::shared_ptr<Component> get(const std::string& name) override;

private:
    // The root shared pointer in componentMap_
    // @param name component name
    // @return root shared component
    std::shared_ptr<Component> getRoot(const std::string& name);
    // Custom deleter of std::shared_ptr
    void release(Component* component);
};

}}
